﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniDAQ_Ns;
using System.Timers;
using System.Configuration;

namespace Common
{
    public class PISO730 : I_IO_Card
    {

        private readonly static object locker = new object();
        public static readonly PISO730 instance = new PISO730();
        System.Timers.Timer tmr = new System.Timers.Timer(10);
        volatile ushort _ReadData = 0;
        volatile ushort Trg = 0;
        volatile ushort Continue = 0;
        public event Action<ushort> TrigEvent;
        public bool isOpen { get; set; }
        public ushort ReadData { get { return _ReadData; } set { _ReadData = value; } }
        private bool inited = false;
    //    public int MyProperty { get; set; }
        public ushort tag { get; set; }

        private PISO730()
        {
            Start();
            tmr.Elapsed += tmr_Elapsed;
        }

        public void Start()
        {
            try
            {
                if (!inited)
                {
                    ushort wTotalBoard = 0;
                    ushort wRtn = UniDAQ.Ixud_DriverInit(ref wTotalBoard);
                    if (wRtn != UniDAQ.Ixud_NoErr)
                    {
                        throw new Exception("Driver Inital Error!!Error Code:" + wRtn.ToString());
                    }
                    inited = true;
                }
                if (!tmr.Enabled)
                {
                    tmr.Start();
                }
             
                isOpen = true;
            //    WriteBit(GenneralConfig.instance.module.DO_RUN, true);
              //  WriteBit(GenneralConfig.instance.module.DO_READ_OK, true);

            }
            catch
            {
                isOpen = false;
            }
        }

        public  void Stop()
        {
            tmr.Stop();
            isOpen = false;
       //     WriteBit(GenneralConfig.instance.module.DO_RUN,false);
        }

        void tmr_Elapsed(object sender, ElapsedEventArgs e)
        {
            lock (locker)
            {
                tmr.Stop();
                _ReadData = (ushort)(Read() & 0xffff);
                Trg = (ushort)(_ReadData & (_ReadData ^ Continue));
                Continue = _ReadData;
                if (Trg != 0 && TrigEvent != null)
                {
                    tag |= Trg;
                    TrigEvent(Trg);
                }
                tmr.Start();
            }
        }

        public static readonly PISO730 Instance = new PISO730();

        public  void Write(uint val)
        {
            if (isOpen)
            {
                ushort wRtn = UniDAQ.Ixud_WriteDO(0, 0, val & 0xff);
                if (wRtn != UniDAQ.Ixud_NoErr)
                {
                    throw new Exception("Driver Write Error!!Error Code:" + wRtn.ToString());
                }
                if (val > 0xff)
                {
                    wRtn = UniDAQ.Ixud_WriteDO(0, 1, val & 0xff00);
                    if (wRtn != UniDAQ.Ixud_NoErr)
                    {
                        throw new Exception("Driver Write Error!!Error Code:" + wRtn.ToString());
                    }
                } 
            }
        }

        public uint Read()
        {
            try
            {
                if (isOpen)
                {
                    uint wDIVal = 0;
                    uint wDIVal1 = 0;
                    ushort wRtn = UniDAQ.Ixud_NoErr;
                    wRtn = UniDAQ.Ixud_ReadDI(0, 0, ref wDIVal);
                    if (wRtn != UniDAQ.Ixud_NoErr)
                    {
                        throw new Exception("Driver Read Error!!Error Code:" + wRtn.ToString());
                    }
                    wRtn = UniDAQ.Ixud_ReadDI(0, 1, ref wDIVal1);
                    if (wRtn != UniDAQ.Ixud_NoErr)
                    {
                        throw new Exception("Driver Read Error!!Error Code:" + wRtn.ToString());
                    }
                    wDIVal = wDIVal + (wDIVal1 << 8);
                    return ~wDIVal;
                }
                else
                    return 0;
            }
            catch 
            {
                
                return 0;
            }
        }

        public bool ReadBit(uint bitNo)
        {
            try
            {
                if (isOpen)
                {
                    ushort wDIVal = 0;
                    ushort port = (ushort)(bitNo / (8));
                    ushort bitNO = (ushort)(bitNo % 8);
                    ushort wRtn = UniDAQ.Ixud_ReadDIBit(0, port, bitNO, ref wDIVal);
                    if (wRtn != UniDAQ.Ixud_NoErr)
                    {
                        throw new Exception("Driver Read Error!!Error Code:" + wRtn.ToString());
                    }
                    return wDIVal > 0 ? false : true;
                }
                else
                    return false;
            }
            catch 
            {
                return false;
            }
        }

        public void AddSubscriber(Action<ushort> method)
        {
            TrigEvent += method;
        }

        public void WriteBit(int bitNo, bool val)
        {
            if (isOpen)
            {
                ushort wRtn = UniDAQ.Ixud_WriteDOBit(0, 0, (ushort)bitNo, (ushort)(val ? 1 : 0));
                if (wRtn != UniDAQ.Ixud_NoErr)
                {
                    throw new Exception("Driver Write Error!!Error Code:" + wRtn.ToString());
                }
            }
        }
    }
}
